package demo.codeanalyzer.processor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.Trees;

public class OwlCodeGenerator extends BaseCodeGenerator implements
		CodeGenerator {

	private Map<String, String> properties = new HashMap<String, String>();

	private Map<String, String> nameSpaces = new HashMap<String, String>();

	private String nameSpace;

	public Object printClass(ClassTree classTree, Trees trees) {
		nameSpace = "&" + element(trees).getEnclosingElement().getSimpleName()
				+ ";";
		boolean isVisible = (null == annotationValue(element(trees),
				"notvisible"));
		ClassPrinter classPrinter = clazz(classTree, trees, visitor,
				properties, nameSpace, isVisible);
		Object result = classPrinter.label(
				annotationValue(element(trees), "rdflabel")).print();
		for (String property : properties.keySet()) {
			System.out.print(properties.get(property));
			properties.put(property, "");
		}

		return result;
	}

	private ClassPrinter clazz(ClassTree classTree, Trees trees,
			PrintingVisitor visitor, Map<String, String> properties,
			String nameSpace2, boolean isVisible) {
		return new GenericClassPrinter(classTree, trees, visitor, properties,
				nameSpaces, nameSpace, isVisible);
	}

	public void printMethod(MethodTree methodTree) {
		// TODO Auto-generated method stub

	}

	public Object printVariable(VariableTree variableTree, Trees trees) {
		String propertyNamespace = annotationValue(element(trees), "namespace");
		if (null == propertyNamespace) {
			propertyNamespace = nameSpace;
		} else {
			propertyNamespace = "&" + unquote(propertyNamespace) + ";";
		}
		PropertyPrinter propertyPrinter = new PropertyPrinter(variableTree,
				trees, visitor, properties, propertyNamespace);
		propertyPrinter.label(annotationValue(element(trees), "rdflabel"));
		return propertyPrinter.print();
	}

	private String unquote(String toUnquote) {
		return toUnquote.replace("\"", "");
	}

	public Object printEnum(ClassTree classTree, Trees trees) {
		handleEnum(classTree);
		Object result = visitor.visitParentClass(classTree, trees);
		return result;
	}

	private void handleEnum(ClassTree classTree) {
		{
			System.out.println("<owl:Class>");
			System.out.println("<owl:oneOf rdf:parseType=\"Collection\">");
			Pattern enumValuePattern = Pattern
					.compile("/[*](.|\\s)*[*]/(.*)/[*](.|\\s)*[*]/");
			List<? extends Tree> members = classTree.getMembers();
			int size = members.size();
			for (int i = 0; i < size; i++) {
				String enumValue = members.get(i).toString();
				Matcher enumValueMatcher = enumValuePattern.matcher(enumValue);
				if (enumValueMatcher.find()) {
					String enumString = String.format(
							"<owl:Thing rdf:about=\"#%s\"/>", enumValueMatcher
									.group(2).trim());
					System.out.println(enumString);
				}
			}
			System.out.println("</owl:oneOf>");
			System.out.println("</owl:Class>");
			System.out.println();
		}
	}

	public Object printNamespaces(ClassTree classTree, Trees trees) {
		nameSpaces.put("xsd", "http://www.w3.org/2001/XMLSchema#");
		nameSpaces.put("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
		nameSpaces.put("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
		return visitor.visitParentClass(classTree, trees);
	}

	public Object processNamespaces(VariableTree variableTree, Trees trees) {
		String nameSpaceValue = variableTree.toString();
		String[] nameSpaceParts = nameSpaceValue.split(" ");
		String nameSpaceIdentifier = null;
		String nameSpaceUri = null;
		for (int i = 0; i < nameSpaceParts.length; i++) {
			if (i == 1) {
				nameSpaceIdentifier = nameSpaceParts[i];
			}
			if (i == 3) {
				nameSpaceUri = nameSpaceParts[i];
			}
		}
		nameSpaces.put(nameSpaceIdentifier, nameSpaceUri);
		return visitor.visitParentVariable(variableTree, trees);
	}
}
